/**
 * 七牛云上传 JS-SDK
 */

/**
 * 函数类型
 */
type AnyFunction = (...args: any[]) => any;

export interface QiniuOptions {
  tokenApiFunc: (...args: any[]) => Promise<any>;
  data: {
    [x: string]: string;
  };
}

/**
 * 针对 upload 函数的数据结构
 */
export interface QiniuUploadOptions {
  file: File;
  options: QiniuOptions;
  next?: AnyFunction;
  error?: AnyFunction;
  complete?: AnyFunction;
}

export function upload(uploadOptions: QiniuUploadOptions) {
  const { file, options } = uploadOptions;
  if (!file) {
    console.error('qiniu uploader need filePath to upload');
    return;
  }
  if (config.qiniuUploadToken) {
    doUpload(uploadOptions);
  } else if (config.qiniuUploadTokenURL) {
    getQiniuToken(() => {
      doUpload(uploadOptions);
    });
  } else if (config.qiniuUploadTokenFunction) {
    config.qiniuUploadToken = config.qiniuUploadTokenFunction();
    if (!config.qiniuUploadToken) {
      console.error(
        'qiniu UploadTokenFunction result is null, please check the return value'
      );
      return;
    }
    doUpload(uploadOptions);
  } else {
    console.error(
      'qiniu uploader need one of [uptoken, uptokenURL, uptokenFunc]'
    );
  }
}

function doUpload(uploadOptions: QiniuUploadOptions) {
  if (!config.qiniuUploadToken) {
    console.error(
      'qiniu UploadToken is null, please check the init config or networking'
    );
    return;
  }
  const {
    filePath,
    success,
    fail,
    options,
    progress,
    cancelTask,
    before,
    complete,
  } = uploadOptions;

  const url = uploadURLFromRegionCode(config?.qiniuRegion || 'ECN');
  if (!url) {
    console.error(
      'qiniu region code is null, please check the init config or networking'
    );
    return;
  }

  console.log('uploadOptions', uploadOptions);

  let fileName = filePath.split('//')[1];
  if (options && options.key) {
    fileName = options.key;
  }
  const formData: { token: string; key?: string } = {
    token: config.qiniuUploadToken,
  };
  if (!config.qiniuShouldUseQiniuFileName) {
    formData.key = fileName;
  }
  before && before();
  const uploadTask = uni.uploadFile({
    url,
    filePath,
    name: 'file',
    formData,
    success(res) {
      const dataString = res.data;
      try {
        const dataObject = JSON.parse(dataString);
        // do something
        const fileURL = `${config.qiniuBucketURLPrefix}/${dataObject.key}`;
        dataObject.fileURL = fileURL;
        // imageURL字段和fileURL字段重复，但本sdk不做删除，因为在最初版本使用的是imageURL。直接删除可能导致原有用户升级至新版sdk后出现异常。
        dataObject.imageURL = fileURL;
        console.log(dataObject);
        if (success) {
          success(dataObject);
        }
      } catch (e) {
        console.log(`parse JSON failed, origin String is: ${dataString}`);
        fail && fail(e);
      }
    },
    fail(error) {
      console.error(error);
      fail && fail(error);
    },
    complete(err) {
      complete && complete(err);
    },
  });

  uploadTask.onProgressUpdate((res) => {
    progress && progress(res);
  });

  cancelTask &&
    cancelTask(() => {
      uploadTask.abort();
    });
}

/**
 * 从指定 URL
 * @param callback
 */
function getQiniuToken(callback: () => void) {
  uni.request({
    url: config.qiniuUploadTokenURL || '',
    success: (res: any) => {
      const token = res.data.uptoken;
      if (token && token.length > 0) {
        config.qiniuUploadToken = token;
        callback && callback();
      } else {
        console.error(
          'qiniuUploader cannot get your token, please check the uptokenURL or server'
        );
      }
    },
    fail(error) {
      console.error(
        'qiniu UploadToken is null, please check the init config or networking: '
      );
      console.error(error);
    },
  });
}

function uploadURLFromRegionCode(code: RegionCode): string | null {
  let uploadURL = null;
  switch (code) {
    case 'ECN':
      uploadURL = 'https://up.qiniup.com';
      break;
    case 'NCN':
      uploadURL = 'https://up-z1.qiniup.com';
      break;
    case 'SCN':
      uploadURL = 'https://up-z2.qiniup.com';
      break;
    case 'NA':
      uploadURL = 'https://up-na0.qiniup.com';
      break;
    case 'ASG':
      uploadURL = 'https://up-as0.qiniup.com';
      break;
    default:
      console.error(
        'please make the region is with one of [ECN, SCN, NCN, NA, ASG]'
      );
  }
  return uploadURL;
}
